package com.dmx.adi;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.dmx.adi.Metadata;
import java.io.*;

public class VODMetadataParser extends MetadataParser {
	private static Log log = LogFactory.getLog(VODMetadataParser.class);
//	private String xml = null;
	public VODMetadataParser() {
		super("");
	}
	public VODMetadataParser(String _xml) {
		super(_xml);
//		this.xml = _xml;
	}
	
	public VODMetadataParser(byte[] _xmlBytes) {
		super(_xmlBytes);
	}
	
	public void parse(ADIMetadata metadata) throws ADIException{
		try {
//			Document document = DocumentHelper.parseText(this.xml);
			SAXReader reader = new SAXReader();
			
			// 隐蔽dtd验证器，不对xml文件进行dtd验证
			reader.setValidation(false);
			reader.setEntityResolver(new EntityResolver() {
				public InputSource resolveEntity(String publicId, String systemId)
						throws SAXException, IOException {
					return new InputSource(new StringBufferInputStream(""));
				}

			});
			// ///////////////////////////////////////////
			
			java.io.ByteArrayInputStream in = new java.io.ByteArrayInputStream(this.xmlBytes);
			
			Document document = reader.read(in);
			Element root = document.getRootElement();
			
			for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
				Element element = (Element) i.next(); 
				treeWalk(element,metadata);
			}
			
		}catch(Exception ex) {
			throw new ADIException("Unexpected Error "+ ex.getMessage()+" Occurred");
		}
	}
	
	public void treeWalk(Element element,ADIMetadata metadata) {
		if (element.getName()!=null && element.getName().equals("Asset")) {
			ADIMetadata _metadata = new ADIMetadata();
			metadata.getChildAsset().add(_metadata);
			metadata = _metadata;
 	   } 
		 for (int i = 0, size = element.nodeCount(); i < size; i++)     {
	           Node node = element.node(i);
	           String nodeName = node.getName();
	           
        	   if (nodeName!=null && nodeName.equals("AMS")) {
         		   Iterator iter=((Element)node).attributeIterator();
        		   while(iter.hasNext()){
       		    		Attribute attr =(Attribute)iter.next();
       		    		String v = attr.getValue()!=null?attr.getValue():"";
       		    		metadata.getAmsMetadata().put(attr.getName(), v);
       		    		metadata.getAppMetadata().add(new Metadata("AMS::"+attr.getName(),
          				   "string",v));
       		    	}
        	   } else if (nodeName!=null && nodeName.equals("App_Data")) {
        		   Element el = (Element)node;
        		   String v = el.attributeValue("Value")!=null?el.attributeValue("Value"):"";
        		   metadata.getAppMetadata().add(new Metadata(el.attributeValue("App")+"::"+el.attributeValue("Name"),
        				   "string",v));
        	   } else if (nodeName!=null && nodeName.equals("Content")) {
        		   metadata.setContent(((Element)node).attributeValue("Value"));
        		   metadata.getAppMetadata().add(new Metadata("Content",
        				   "string", metadata.getContent()));
        	   }

	           
	           if (node instanceof Element) {
	        	   treeWalk((Element) node,metadata); 
	        	   
	           } 
		 }
		
	}

	public String parseMetadata(List<Metadata> _packageMetadata, List<List<Metadata>> _assetMetadataList) {
		
		String provider = null;
		String asset_ID = null;
		
		try {
			SAXReader reader = new SAXReader();
			java.io.ByteArrayInputStream in = new java.io.ByteArrayInputStream(this.xmlBytes);
			reader.setValidation(false);
			Document document = reader.read(in); //DocumentHelper.parseText(this.xml);

			Element node = (Element) document.selectSingleNode("//ADI/Metadata/AMS"); 
			Iterator iter=node.attributeIterator();
		    while(iter.hasNext()){
		    	Attribute attr =(Attribute)iter.next();
		    	_packageMetadata.add(new Metadata("AMS::"+attr.getName(),"string",attr.getValue()));
		    	
		    	if (attr.getName().equals("Provider")) {
		    		provider = attr.getValue();
		    	} else if (attr.getName().equals("Asset_ID")) {
		    		asset_ID = attr.getValue();
		    	} 
		    }
			
			List list = document.selectNodes("//ADI/Asset"); 
			
			Iterator iter1=list.iterator();
			while(iter1.hasNext()){
				Element element=(Element)iter1.next();
				Iterator iter2=element.elementIterator("Asset");
				List<Metadata> _metadataList = new ArrayList<Metadata>();
				while(iter2.hasNext()) {
					Element _element1 =(Element)iter2.next();
					Element _element2 = (Element) _element1.selectSingleNode("./Metadata/AMS");
					if (_element2.attributeValue("AMS::Asset_Class").equals("movie")) {
						_metadataList.add(new Metadata("AMS::Asset_Name","string",_element2.attributeValue("Asset_Name")));
						_metadataList.add(new Metadata("AMS::Asset_ID","string",_element2.attributeValue("Asset_ID")));
						_metadataList.add(new Metadata("AMS::Asset_Class","string",_element2.attributeValue("Asset_Class")));
						_metadataList.add(new Metadata("AMS::Provider","string",_element2.attributeValue("Provider")));
						_metadataList.add(new Metadata("AMS::Provider_ID","string",_element2.attributeValue("Provider_ID")));
						_metadataList.add(new Metadata("AMS::Product","string",_element2.attributeValue("Product")));
						_metadataList.add(new Metadata("AMS::Version_Minor","string",_element2.attributeValue("Version_Minor")));
						_metadataList.add(new Metadata("AMS::Version_Major","string",_element2.attributeValue("Version_Major")));
						_metadataList.add(new Metadata("AMS::Creation_Date","string",_element2.attributeValue("Creation_Date")));
						_metadataList.add(new Metadata("AMS::Bit_Rate","string",((Element)_element1.selectSingleNode("./Metadata/App_Data[@Name='Bit_Rate']")).attributeValue("Value")));
						_metadataList.add(new Metadata("AMS::Content_FileSize","string",((Element)_element1.selectSingleNode("./Metadata/App_Data[@Name='Content_FileSize']")).attributeValue("Value")));
						_metadataList.add(new Metadata("AMS::Content","string",((Element) _element1.selectSingleNode("./Content")).attributeValue("Value")));
						
//						String asset_Name = _element2.attributeValue("Asset_Name");
//						String asset_ID = _element2.attributeValue("Asset_ID");
//						String asset_Class = _element2.attributeValue("Asset_Class");
//						String provider = _element2.attributeValue("Provider");
//						String provider_ID = _element2.attributeValue("Provider_ID");
//						String product = _element2.attributeValue("Product");
//						String version_Minor = _element2.attributeValue("Version_Minor");
//						String version_Major = _element2.attributeValue("Version_Major"); 
//						String description = _element2.attributeValue("Description=");
//						String creation_Date = _element2.attributeValue("Creation_Date");
//						String bit_Rate = ((Element)_element1.selectSingleNode("./Metadata/App_Data[@Name='Bit_Rate']")).attributeValue("Value");
//						String content_Size = ((Element)_element1.selectSingleNode("./Metadata/App_Data[@Name='Content_FileSize']")).attributeValue("Value");
//						String content_Name = ((Element) _element1.selectSingleNode("./Content")).attributeValue("Value");
						
					}
				}
				
				_assetMetadataList.add(_metadataList);

			}

			return provider+"_"+asset_ID;
		} catch (DocumentException e) {
		} 
		
		return "";

	}

	public String version() {
		return Constants.CableLabsVOD11;
	}
	
	public static void main(String[] args){
		ADIMetadata adidata = new ADIMetadata();
		VODMetadataParser parse=new VODMetadataParser();
		
		try {
			InputStream is=new FileInputStream("C:\\ADI.xml");
			byte[] xmlBytes=new byte[is.available()];
			is.read(xmlBytes);
			
			String str=new String(xmlBytes);
			parse.xmlBytes=str.getBytes("utf-8");
			parse.parse(adidata);
			
			/*System.out.println("child size="+adidata.getChildAsset().size());
			System.out.println(adidata.getChildAsset().get(0).getAmsMetadata().size());
			System.out.println("child size="+adidata.getChildAsset().get(0).getChildAsset().size());*/
			
			/*List<ADIMetadata> l= adidata.getChildAsset().get(0).getChildAsset();
			for(ADIMetadata am:l){
				Map<String,String> amsMetadata=am.getAmsMetadata();
				System.out.println("Asset_Class="+amsMetadata.get("Asset_Name"));
				List<MetadataModule.Metadata> ml=am.getAppMetadata();
				for(MetadataModule.Metadata m:ml){
					System.out.println(m.name+"="+m.value);
				}
			}*/
			
			/*for(Iterator it=adidata.getAmsMetadata().keySet().iterator();it.hasNext();){
				String key=it.next().toString();
				System.out.println(key+"=="+adidata.getAmsMetadata().get(key));
			}*/
			
			Map<String, List<Map<String, String>>> map = new HashMap<String, List<Map<String, String>>>();
			map = parse.getMetaData2(map, adidata);
			
			List<Map<String, String>> packageMap = map.get("package");
			List<Map<String, String>> appdataPackageMap = map.get("APPDATApackage");
			
			List<Map<String, String>> categoryMap = map.get("category");
			List<Map<String, String>> appdataCategoryMap = map.get("APPDATAcategory");
			
			List<Map<String, String>> newsListMap = map.get("news");
			List<Map<String, String>> appdataNewsListMap = map.get("APPDATAnews");
			
			System.out.println(packageMap.size());
			System.out.println(appdataPackageMap.size());
			
			Map<String, String> m1=categoryMap.get(0);
			Map<String, String> m2=appdataPackageMap.get(0);
			
			System.out.println(m1.get("Content"));
			System.out.println(m2.get("NOD::Languages"));
			
			/*System.out.println("appdataNewsMap.size:"+appdataNewsMap.size());
			for(Iterator it=appdataNewsMap.keySet().iterator();it.hasNext();){
				String key=it.next().toString();
				System.out.println(key+"=="+appdataNewsMap.get(key));
			}*/
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage(),e);
		}
	}
	
	private Map<String, Map<String, String>> getMetaData(
			Map<String, Map<String, String>> map, ADIMetadata adidata) {
		if (adidata.getAmsMetadata() != null) {
			Map<String, String> temp = adidata.getAmsMetadata();

			temp.put("Content", adidata.getContent());
			
			if (temp.get("Asset_Class") != null) {
				map.put(temp.get("Asset_Class").toString(), temp);
			}

			if (adidata.getChildAsset().size() > 0) {
				for (ADIMetadata sub : adidata.getChildAsset()) {
					getMetaData(map, sub);
				}
			}

			if (adidata.getAppMetadata() != null) {
				Map<String, String> appdata = new HashMap<String, String>();
				insertvalue(appdata, adidata.getAppMetadata());
				map.put("APPDATA" + temp.get("Asset_Class"), appdata);
			}
		}

		return map;
	}
	
	private Map<String, List<Map<String, String>>> getMetaData2(
			Map<String, List<Map<String, String>>> listMap, ADIMetadata adidata) {
		List<Map<String, String>> list=null;
		if (adidata.getAmsMetadata() != null) {
			Map<String, String> temp = adidata.getAmsMetadata();

			temp.put("Content", adidata.getContent());
			
			if (temp.get("Asset_Class") != null) {
				if(listMap.get(temp.get("Asset_Class"))==null){
					list=new ArrayList<Map<String, String>>();
				}else{
					list=listMap.get(temp.get("Asset_Class"));
				}
				list.add(temp);
				listMap.put(temp.get("Asset_Class").toString(), list);
			}

			if (adidata.getChildAsset().size() > 0) {
				for (ADIMetadata sub : adidata.getChildAsset()) {
					getMetaData2(listMap, sub);
				}
			}

			if (adidata.getAppMetadata() != null) {
				Map<String, String> appdata = new HashMap<String, String>();
				insertvalue(appdata, adidata.getAppMetadata());
				
				if(listMap.get("APPDATA" + temp.get("Asset_Class"))==null){
					list=new ArrayList<Map<String, String>>();
				}else{
					list=listMap.get("APPDATA" + temp.get("Asset_Class"));
				}
				list.add(appdata);
				listMap.put("APPDATA" + temp.get("Asset_Class"), list);
			}
		}

		return listMap;
	}	

	
	private Map<String, String> insertvalue(Map<String, String> map,
			List<Metadata> list) {
		if (list != null && map != null) {
			for (Metadata meta : list) {
				if (meta.name.indexOf("AMS::") < 0) {
					if (map.get(meta.name) != null) {
						map.put(meta.name, meta.value + ","
								+ map.get(meta.name));

					} else {
						map.put(meta.name, meta.value);
					}
				}

			}
		}
		return map;
	}
	
	private static String getValueFromMap(String key, Map map) {
		if (map == null)
			return null;
		return map.get(key) == null ? "" : map.get(key).toString();
	}
	
	
}
